#pragma once
#include <iostream>
#include <memory>
#include <stack>
#include <vector>

#include <string.h>
#include <string>
#include <stdio.h>


using namespace std;

//抽象表达式类Node（抽象节点）
class Node {
	public:
		virtual int interpret() = 0;
};

//终结符表达式类ValueNode（值节点类）
class ValueNode : public Node {
	public:
		ValueNode(int value) {
			this->value = value;
		}
		
		int interpret(){
			return this->value;
		}
	private:
		int value = 0;
};


//抽象非终结符表达式类SymbolNode（符号节点类）
class SymbolNode : public Node {
	public:
		SymbolNode(shared_ptr<Node> left,shared_ptr<Node> right) {
			this->left = left;
			this->right = right;
		}
	protected:
		shared_ptr<Node> left;
		shared_ptr<Node> right;
};

//非终结符表达式类MulNode（乘法节点类）
class MulNode : public SymbolNode {
	public:
		MulNode(shared_ptr<Node> left,shared_ptr<Node> right) : SymbolNode(left,right) {
 
		}
 
		int interpret() {
			return left->interpret()*right->interpret();
		}
};


//非终结符表达式类DivNode（除法节点类）
class DivNode : public SymbolNode {
	public:
		DivNode(shared_ptr<Node> left,shared_ptr<Node> right) : SymbolNode(left,right) {
 
		}
 
		int interpret() {
			return left->interpret()/right->interpret();
		}
};


//非终结符表达式类ModNode（求模节点类）
class ModNode : public SymbolNode {
	public:
		ModNode(shared_ptr<Node> left,shared_ptr<Node> right) : SymbolNode(left,right) {
 
		}
 
		int interpret() {
			return left->interpret()%right->interpret();
		}
};


//解析器封装类Calculator（计算器类）
class Calculator {
	public:
		void bulid(string statement) {
			shared_ptr<Node> left,right;
			stack<shared_ptr<Node> > s;
			
			//分割语义 
			vector<string> statementArr = split(statement,' ');
		    
			//处理语义
			for(int i = 0 ; i < statementArr.size() ; i++){
				if(statementArr[i] == "*"){
					left = s.top(); s.pop();
					int val = atoi(statementArr[++i].c_str());
					right = make_shared<ValueNode>(val);
					s.push(make_shared<MulNode>(left,right));
				}else if(statementArr[i] == "/"){
					left = s.top(); s.pop();
					int val = atoi(statementArr[++i].c_str());
					right = make_shared<ValueNode>(val);
					s.push(make_shared<DivNode>(left,right));
				}else if(statementArr[i] == "%"){
					left = s.top(); s.pop();
					int val = atoi(statementArr[++i].c_str());
					right = make_shared<ValueNode>(val);
					s.push(make_shared<ModNode>(left,right));
				}else{
					s.push(make_shared<ValueNode>(atoi(statementArr[i].c_str())));
				}
			}
			this->node = s.top(); s.pop();
		}
		
		int compute(){
			return node->interpret();
		}
	private:
		string statement;
		shared_ptr<Node> node;
};